/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.bpm.core.json.converter.json.converter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.je.bpm.core.json.converter.json.converter.factory.AssignmentConfigFactory;
import com.je.bpm.core.model.config.task.assignment.*;
import com.je.bpm.core.model.task.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 凯特用户任务指派人基础json解析器
 */
public abstract class AbstractKaiteAssignmentUserTaskJsonConverter extends AbstractKaiteBaseUserTaskJsonConverter {

    /**
     * 转换指派人
     *
     * @param taskAssigneeConfig
     * @return
     */
    protected void fillUserTaskAssigneeConfigToJson(TaskAssigneeConfigImpl taskAssigneeConfig, ObjectNode propertiesNode) {
        ObjectNode taskAssigneeNode = objectMapper.createObjectNode();
        ArrayNode assignmentResource = objectMapper.createArrayNode();
        if (taskAssigneeConfig.getReferTo() == null) {
            taskAssigneeNode.put(PROPERTY_ASSIGNMENT_REFERTONAME_CONFIG, "");
            taskAssigneeNode.put(PROPERTY_ASSIGNMENT_REFERTOCODE_CONFIG, "");
        } else {
            taskAssigneeNode.put(PROPERTY_ASSIGNMENT_REFERTONAME_CONFIG, taskAssigneeConfig.getReferTo().getName());
            taskAssigneeNode.put(PROPERTY_ASSIGNMENT_REFERTOCODE_CONFIG, taskAssigneeConfig.getReferTo().toString());
        }
        List<BasicAssignmentConfigImpl> basicAssignmentConfigList = taskAssigneeConfig.getResource();
        for (BasicAssignmentConfigImpl assignmentConfig : basicAssignmentConfigList) {
            ObjectNode itemNode = objectMapper.createObjectNode();
            itemNode.put(UNIVERSAL_TYPE, assignmentConfig.getConfigType());
            itemNode.put(UNIVERSAL_NAME, assignmentConfig.getConfigTypeName());
            ObjectNode itemConfigNode = objectMapper.createObjectNode();
            //角色、部门、岗位
            if (assignmentConfig instanceof PositionAssignmentConfigImpl ||
                    assignmentConfig instanceof DepartmentAssignmentConfigImpl
                    || assignmentConfig instanceof RoleAssignmentConfigImpl) {
                List<AssigneeResource> itemNodeAssigneeList = assignmentConfig.getResource();
                parseAssignmentResourceToJson(itemNodeAssigneeList, itemConfigNode);
                parseAssignmentPermissionToJson(assignmentConfig.getPermission(), itemConfigNode);
            }
            //人员、表单字段
            if (assignmentConfig instanceof UserAssignmentConfigImpl ||
                    assignmentConfig instanceof FormFieldAssignmentConfigImpl) {
                List<AssigneeResource> itemNodeAssigneeList = assignmentConfig.getResource();
                parseAssignmentResourceToJson(itemNodeAssigneeList, itemConfigNode);
            }

            //组织架构
            if (assignmentConfig instanceof OrgTreeAssignmentConfigImpl) {
                OrgTreeAssignmentConfigImpl orgTreeAssignmentConfig = (OrgTreeAssignmentConfigImpl) assignmentConfig;
                itemConfigNode.put(UNIVERSAL_ENABLE, orgTreeAssignmentConfig.isEnable());
            }

            //自定义service
            if (assignmentConfig instanceof CustomAssignmentConfigImpl) {
                CustomAssignmentConfigImpl customAssignmentConfig = (CustomAssignmentConfigImpl) assignmentConfig;
                itemConfigNode.put(PROPERTY_ASSIGNMENT_CUSTOM_SERVICENAME, customAssignmentConfig.getServiceName());
                itemConfigNode.put(PROPERTY_ASSIGNMENT_CUSTOM_METHODNAME, customAssignmentConfig.getMethodName());
            }

            //特殊处理
            if (assignmentConfig instanceof SpecialAssignmentConfigImpl) {
                SpecialAssignmentConfigImpl specialAssignmentConfig = (SpecialAssignmentConfigImpl) assignmentConfig;
                List<SpecialAssignmentConfigImpl.SpectialTypeEnum> list = specialAssignmentConfig.getSpecialType();
                for (SpecialAssignmentConfigImpl.SpectialTypeEnum typeEnum : list) {
                    itemConfigNode.put(typeEnum.toString(), typeEnum.getDesc());
                }
            }

            //sql
            if (assignmentConfig instanceof BusinessSqlAssignmentConfigImpl) {
                BusinessSqlAssignmentConfigImpl sqlAssignmentConfig = (BusinessSqlAssignmentConfigImpl) assignmentConfig;
                itemConfigNode.put(UNIVERSAL_SQL, sqlAssignmentConfig.getSql());
            }

            itemNode.set(UNIVERSAL_CONFIG, itemConfigNode);
            itemNode.put(PROPERTY_ASSIGNMENT_ENTRY_PATH_CONFIG, assignmentConfig.getEntryPath());
            assignmentResource.add(itemNode);
        }
        taskAssigneeNode.set(UNIVERSAL_RESOURCE, assignmentResource);
        propertiesNode.set(PROPERTY_ASSIGNMENT_CONFIG, taskAssigneeNode);
    }

    /**
     * resource资源信息
     *
     * @param itemNodeAssigneeList
     * @param itemConfigNode
     */
    private void parseAssignmentResourceToJson(List<AssigneeResource> itemNodeAssigneeList, ObjectNode itemConfigNode) {
        ArrayNode itemNodeResource = objectMapper.createArrayNode();
        for (AssigneeResource assigneeResource : itemNodeAssigneeList) {
            ObjectNode resource = objectMapper.createObjectNode();
            resource.put(UNIVERSAL_ID, assigneeResource.getId());
            resource.put(UNIVERSAL_CODE, assigneeResource.getCode());
            resource.put(UNIVERSAL_NAME, assigneeResource.getName());
            itemNodeResource.add(resource);
        }
        itemConfigNode.set(UNIVERSAL_RESOURCE, itemNodeResource);
    }

    /**
     * 权限
     *
     * @param assignmentPermission
     * @param itemConfigNode
     */
    private void parseAssignmentPermissionToJson(AssignmentPermission assignmentPermission, ObjectNode itemConfigNode) {
        ObjectNode itemNodePermission = objectMapper.createObjectNode();
        if (assignmentPermission.getCompany()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_COMPANY, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_COMPANY, 0);
        }
        if (assignmentPermission.getCompanySupervision()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_COMPANY_SUPERVISION, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_COMPANY_SUPERVISION, 0);
        }
        if (assignmentPermission.getDept()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DEPT, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DEPT, 0);
        }
        if (assignmentPermission.getDeptAll()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DEPT_ALL, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DEPT_ALL, 0);
        }
        if (assignmentPermission.getDirectLeader()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DIRECT_LEADER, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DIRECT_LEADER, 0);
        }
        if (assignmentPermission.getDeptLeader()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DEPT_LEADER, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_DEPT_LEADER, 0);
        }
        if (assignmentPermission.getSupervisionLeader()) {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_SUPERVISION_LEADER, 1);
        } else {
            itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_SUPERVISION_LEADER, 0);
        }
        itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_SQL, assignmentPermission.getSql());
        itemNodePermission.put(PROPERTY_ASSIGNMENT_PERMISSION_SQL_REMARKS, assignmentPermission.getSqlRemarks());
        itemConfigNode.set(PROPERTY_ASSIGNMENT_PERMISSION_CONFIG, itemNodePermission);
    }

    protected void parseUserTaskJsonToAssigneeConfig(JsonNode elementNode, KaiteBaseUserTask userTask) {
        JsonNode taskAssigneeNode = elementNode.get(PROPERTY_ASSIGNMENT_CONFIG);
        TaskAssigneeConfigImpl taskAssigneeConfig = new TaskAssigneeConfigImpl();
        String referToCode = getValueAsString(PROPERTY_ASSIGNMENT_REFERTOCODE_CONFIG, taskAssigneeNode);
        TaskAssigneeConfigImpl.ReferToEnum referToEnum = TaskAssigneeConfigImpl.ReferToEnum.getReferToEnumCode(referToCode);
        taskAssigneeConfig.setReferTo(referToEnum);

        List<BasicAssignmentConfigImpl> resources = new ArrayList<>();
        ArrayNode assignmentResource = (ArrayNode) taskAssigneeNode.get(UNIVERSAL_RESOURCE);
        for (JsonNode resource : assignmentResource) {
            BasicAssignmentConfigImpl basicAssignmentConfig = AssignmentConfigFactory.getAssignmentConfigByJson
                    (getValueAsString(UNIVERSAL_TYPE, resource), resource);
            resources.add(basicAssignmentConfig);
        }
        taskAssigneeConfig.setResource(resources);
        if (userTask instanceof KaiteUserTask) {
            ((KaiteUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        } else if (userTask instanceof KaiteCandidateUserTask) {
            ((KaiteCandidateUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        } else if (userTask instanceof KaiteCounterSignUserTask) {
            ((KaiteCounterSignUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        } else if (userTask instanceof KaiteDecideUserTask) {
            ((KaiteDecideUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        } else if (userTask instanceof KaiteFixedUserTask) {
            ((KaiteFixedUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        } else if (userTask instanceof KaiteLoopUserTask) {
            ((KaiteLoopUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        } else if (userTask instanceof KaiteMultiUserTask) {
            ((KaiteMultiUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        }else if (userTask instanceof KaiteRandomUserTask) {
            ((KaiteRandomUserTask) userTask).setTaskAssigneeConfig(taskAssigneeConfig);
        }
    }

}
